home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / os2 / ue311gcc.zip / MOUSE.C < prev    next >
C/C++ Source or Header  |  1992-12-29  |  16KB  |  654 lines

  1. /*    MOUSE.C:    Mouse functionality commands
  2.             for MicroEMACS 3.10
  3.             originally written by Dave G. Conroy
  4.             modified by Jeff Lomicka and Daniel Lawrence
  5. */
  6.  
  7. #include    <stdio.h>
  8. #include    "estruct.h"
  9. #include    "eproto.h"
  10. #include        "edef.h"
  11. #include    "elang.h"
  12.  
  13. #define    MNONE    0            /* Mouse commands.        */
  14. #define    MMOVE    1
  15. #define    MREG    2
  16. #define    MCREATE    3
  17. #define MDELETE    4
  18.  
  19. #if    MOUSE
  20. NOSHARE int    lastypos = HUGE;    /* Last mouse event row.    */
  21. NOSHARE int    lastxpos = HUGE;    /* Last mouse event column.    */
  22. NOSHARE int    lastmcmd = MNONE;    /* Last mouse command.        */
  23. #endif
  24.  
  25. #if    WINDOW_TEXT
  26.  
  27. /* Redraw given screen and all screens behind it */
  28.  
  29. void PASCAL NEAR refresh_screen(sp)
  30.  
  31. SCREEN *sp;    /* screen image to refresh */
  32.  
  33. {
  34.     /* if we are suppressing redraws */
  35.     if (gflags & GFSDRAW)
  36.         return;
  37.  
  38.     /* at end of list, do nothing */
  39.     if (sp == (SCREEN *)NULL)
  40.         return;
  41.  
  42.     /* if first refresh, erase the page */
  43.     if (sp == first_screen) {
  44.         (*term.t_clrdesk)();
  45.         if (sp->s_next_screen == (SCREEN *)NULL)
  46.             sgarbf = TRUE;
  47.     }
  48.  
  49.     /* if there are others below, defer to them first */
  50.     if (sp->s_next_screen)
  51.         refresh_screen(sp->s_next_screen);
  52.  
  53.     select_screen(sp, FALSE);
  54.     update(TRUE);
  55. }
  56. #endif
  57.  
  58. #if    MOUSE
  59. /*
  60.  * Move mouse button, down. The window that the
  61.  * mouse is in is always selected (this lets you select a
  62.  * window by clicking anyplace in it, even off the end
  63.  * of the text). If the mouse points at text then dot is
  64.  * moved to that location.
  65.  */
  66. PASCAL NEAR movemd(f, n)
  67.  
  68. int f,n;    /* prefix flag and argument */
  69.  
  70. {
  71.     register WINDOW    *wp;
  72.     register WINDOW    *lastwp;
  73.     register LINE    *lp;
  74.  
  75.     /* make sure we are on the proper screen */
  76.     mouse_screen();
  77.  
  78.     /* adjust position by screen offset */
  79.     ypos -= term.t_roworg;
  80.     xpos -= term.t_colorg;
  81.  
  82.     /* if anything has changed, reset the click count */
  83.     if (lastmcmd != MMOVE || lastypos!=ypos || lastxpos!=xpos)
  84.         nclicks = 0;
  85.     ++nclicks;
  86.     lastwp = mousewindow(lastypos);        /* remember last window */
  87.  
  88.     /* reset the last position */
  89.     lastypos = ypos;
  90.     lastxpos = xpos;
  91.     lastmcmd = MMOVE;
  92.  
  93.     /* if we move the mouse off the windows, don't do anything with it */
  94.     if ((wp=mousewindow(ypos)) == NULL)
  95.         return(FALSE);
  96.  
  97.     /* if we are on the line with the point, adjust for extended lines */
  98.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  99.         xpos += lbound;
  100.  
  101.     /* make the window the mouse points to current */
  102.     curwp = wp;
  103.     curbp = wp->w_bufp;
  104.  
  105.     /* if we changed windows, update the modelines */
  106.     if (wp != lastwp)
  107.         upmode();
  108.  
  109.     /* if we aren't off the end of the text, move the point to the mouse */
  110.     if ((lp=mouseline(wp, ypos)) != NULL) {
  111.         curwp->w_dotp = lp;
  112.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  113.     }
  114.  
  115.     return(TRUE);
  116. }
  117.  
  118.  
  119. /*    mouse-region-down:    mouse region operations
  120.  
  121.     nclicks = 0:    move cursor to mouse
  122.             set-mark
  123.  
  124.           1:    move cursor to mouse
  125.             kill-region
  126. */
  127.  
  128. PASCAL NEAR mregdown(f, n)
  129.  
  130. int f,n;    /* prefix flag and argument */
  131.  
  132. {
  133.     register WINDOW    *wp;
  134.     register WINDOW    *lastwp;
  135.     register LINE    *lp;
  136.     SCREEN *sp;
  137.     char scr_name[12];        /* constructed temp screen name */
  138.     static int temp_count = 0;    /* next temp screen number! */
  139.  
  140.     /* make sure we are on the proper screen */
  141.     mouse_screen();
  142.  
  143.     /* adjust position by screen offset */
  144.     ypos -= term.t_roworg;
  145.     xpos -= term.t_colorg;
  146.  
  147.     /* if anything has changed, reset the click count */
  148.     if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
  149.         nclicks = 0;
  150.     ++nclicks;
  151.     lastwp = mousewindow(lastypos);        /* remember last window */
  152.  
  153.     /* reset the last position */
  154.     lastypos = ypos;
  155.     lastxpos = xpos;
  156.     lastmcmd = MREG;
  157.  
  158.     /* if we are in the upper left corner, create a new window */
  159.     if (xpos == 0 && ypos == 0) {
  160.  
  161.         /* get the name of the screen to create */
  162.         strcpy(scr_name, "SCREEN");
  163.         strcat(scr_name, int_asc(temp_count++));
  164.         while (lookup_screen(scr_name) != (SCREEN *)NULL) {
  165.             strcpy(scr_name, "SCREEN");
  166.             strcat(scr_name, int_asc(temp_count++));
  167.         }
  168.     
  169.         /* save the current dot position in the buffer info
  170.            so the new screen will start there! */
  171.         curbp->b_dotp = curwp->w_dotp;
  172.         curbp->b_doto = curwp->w_doto;
  173.  
  174.         /* screen does not exist, create it */
  175.         sp = init_screen(scr_name, curbp);
  176.     
  177.         /* and make this screen current */
  178.         return(select_screen(sp, TRUE));
  179.     }
  180.  
  181.     /* if we move the mouse off the windows, don't move anything */
  182.     if ((wp=mousewindow(ypos)) == NULL)
  183.         return(FALSE);
  184.  
  185.     /* if we are on the line with the point, adjust for extended lines */
  186.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  187.         xpos += lbound;
  188.  
  189.     /* make the window the mouse points to current */
  190.     curwp = wp;
  191.     curbp = wp->w_bufp;
  192.  
  193.     /* if we changed windows, update the modelines */
  194.     if (wp != lastwp)
  195.         upmode();
  196.  
  197.     /* if we aren't off the end of the text, move the point to the mouse */
  198.     if ((lp=mouseline(wp, ypos)) != NULL) {
  199.         curwp->w_dotp = lp;
  200.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  201.     }
  202.  
  203.     /* perform the region function */
  204.     if (nclicks == 1) {
  205.         return(setmark(FALSE, 0));
  206.     } else {
  207.         lastflag &= ~CFKILL;
  208.         return(killregion(FALSE, 0));
  209.     }
  210. }
  211.  
  212. /*    mouse-region-up:    mouse region operations
  213.  
  214.     If the corrosponding downclick was on a modeline, then we
  215.     wish to delete the indicated window. Otherwise we are using
  216.     this button to copy/paste.
  217.  
  218.     nclicks = 0:    move cursor to mouse
  219.             copy-region
  220.  
  221.           1:    move cursor to mouse
  222.             yank
  223.  
  224.           3:    reset nclicks to 0
  225. */
  226.  
  227. PASCAL NEAR mregup(f, n)
  228.  
  229. int f,n;    /* prefix flag and argument */
  230.  
  231. {
  232.     register WINDOW    *wp;
  233.     register WINDOW    *lastwp;
  234.     register LINE *lp;
  235.     register SCREEN *sp;        /* ptr to screen to delete */
  236.     register int lastmodeline;    /* was the dowbclick on a modeline? */
  237.     register int lastcmdline;    /* was the downclick on the command line? */
  238.  
  239.     /* adjust position by screen offset */
  240.     ypos -= term.t_roworg;
  241.     xpos -= term.t_colorg;
  242.  
  243.     /* if anything has changed, reset the click count */
  244.     if (lastmcmd != MREG || lastypos != ypos || lastxpos != xpos)
  245.         nclicks = 0;
  246.     ++nclicks;
  247.     lastwp = mousewindow(lastypos);        /* remember last window */
  248.  
  249.     /* if the down click was in the upper left corner...
  250.        then we are moving a just created screen */
  251.     if (lastypos == 0 && lastxpos == 0) {
  252.         new_row_org(TRUE, ypos + term.t_roworg);
  253.         new_col_org(TRUE, xpos + term.t_colorg);
  254. #if    WINDOW_TEXT
  255.         refresh_screen(first_screen);
  256. #endif
  257.         return(TRUE);
  258.     }
  259.  
  260.     /* Just where was the last click? */
  261.     lastmodeline = ismodeline(lastwp, lastypos);
  262.     lastcmdline = (lastypos == term.t_nrow);
  263.  
  264.     /* reset the last position */
  265.     lastypos = ypos;
  266.     lastxpos = xpos;
  267.     lastmcmd = MREG;
  268.  
  269.     /* if we started on a modeline.... */
  270.     if (lastmodeline)
  271.         return(delwind(TRUE, 0));
  272.  
  273.     /* if we are on a command line */
  274.     if (lastcmdline) {
  275.         if (ypos != term.t_nrow)
  276.  
  277.             /* ABORT ABORT ABORT screen deletion */
  278.             return(TRUE);
  279.         else {
  280.  
  281.             /* delete the screen last screen means exiting */
  282.             if (first_screen->s_next_screen == (SCREEN *)NULL)
  283.                 return(quit(FALSE, 0));
  284.  
  285.             /* bring the second last screen to front*/
  286.             sp = first_screen;
  287.             select_screen(sp->s_next_screen, FALSE);
  288.  
  289.             /* and dump the front screen */
  290.             first_screen->s_next_screen = sp->s_next_screen;
  291.             free_screen(sp);
  292. #if    WINDOW_TEXT
  293.             refresh_screen(first_screen);
  294. #endif
  295.             return(TRUE);
  296.         }
  297.     }
  298.  
  299.     /* if we move the mouse off the windows, don't move anything */
  300.     if ((wp=mousewindow(ypos)) == NULL)
  301.         return(FALSE);
  302.  
  303.     /* if we are on the line with the point, adjust for extended lines */
  304.     if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
  305.         xpos += lbound;
  306.  
  307.     /* make the window the mouse points to current */
  308.     curwp = wp;
  309.     curbp = wp->w_bufp;
  310.  
  311.     /* if we aren't off the end of the text, move the point to the mouse */
  312.     if ((lp=mouseline(wp, ypos)) != NULL && nclicks < 3) {
  313.         curwp->w_dotp = lp;
  314.         curwp->w_doto = mouseoffset(wp, lp, xpos);
  315.     }
  316.  
  317.     /* if we changed windows, update the modelines, abort the new op */
  318.     if (wp != lastwp) {
  319.         upmode();
  320.         return(TRUE);
  321.     }
  322.  
  323.     /* perform the region function */
  324.     if (nclicks == 1) {
  325.         return(copyregion(FALSE, 0));
  326.     } else if (nclicks == 2) {
  327.         return(yank(FALSE, 1));
  328.     } else {
  329.         nclicks = 0;
  330.         return(TRUE);
  331.     }
  332. }
  333.  
  334. /*
  335.  * Move mouse button, up. The up click must be
  336.  * in the text region of a window. If the old click was in a
  337.  * mode line then the mode line moves to the row of the
  338.  * up click. If the old click is not in a mode line then the
  339.  * window scrolls. The code in this function is just
  340.  * too complex!
  341.  */
  342. PASCAL NEAR movemu(f, n)
  343.  
  344. int f,n;    /* prefix flag and argument */
  345.  
  346. {
  347.     register WINDOW    *lastwp;
  348.     register WINDOW    *wp;
  349.     register int lastmodeline;    /* was the downclick on a modeline? */
  350.     register int deltay;
  351.     register int deltax;
  352. #if    WINDOW_TEXT
  353.     register int redraw_needed;    /* is a screen redraw required */
  354. #endif
  355.  
  356.     /* adjust position by screen offset */
  357.     ypos -= term.t_roworg;
  358.     xpos -= term.t_colorg;
  359.  
  360.     /* no movement... fail the command */
  361.     if (lastypos==ypos && lastxpos==xpos)
  362.         return(FALSE);
  363.  
  364.     /* if the down click was in the bottom right corner...
  365.        then we are resizing */
  366.     if (lastypos == term.t_nrow && lastxpos + 1 == term.t_ncol) {
  367. #if    WINDOW_TEXT
  368.         if (xpos < term.t_ncol || ypos < term.t_nrow)
  369.             redraw_needed = TRUE;
  370.         else
  371.             redraw_needed = FALSE;
  372. #endif
  373.         newwidth(TRUE, xpos + 1);
  374.         newsize(TRUE, ypos + 1);
  375. #if    WINDOW_TEXT
  376.         if (redraw_needed) {
  377.             refresh_screen(first_screen);
  378.         }
  379. #endif
  380.         return(TRUE);
  381.     }
  382.  
  383.     /* if the down click was in the upper left corner...
  384.        then we are moving the screen */
  385.     if (lastypos == 0 && lastxpos == 0) {
  386.         new_row_org(TRUE, ypos + term.t_roworg);
  387.         new_col_org(TRUE, xpos + term.t_colorg);
  388. #if    WINDOW_TEXT
  389.         refresh_screen(first_screen);
  390. #endif
  391.         return(TRUE);
  392.     }
  393.  
  394.     /* if the down click was not in a window.. fail the command
  395.        (for example, if we click on the command line) */
  396.     if ((lastwp=mousewindow(lastypos)) == NULL)
  397.         return(FALSE);
  398.  
  399.     /* did we down click on a modeline? */
  400.     lastmodeline = ismodeline(lastwp, lastypos);
  401.  
  402.     /* are we not in a window? fail it then */
  403.     if ((wp=mousewindow(ypos)) == NULL)
  404.         return(FALSE);
  405.  
  406.     /* how far did we move? */
  407.     deltay = lastypos-ypos;
  408.     deltax = lastxpos-xpos;
  409.     lastypos = ypos;
  410.     lastxpos = xpos;
  411.  
  412.     /* if we started on a modeline.... */
  413.     if (lastmodeline) {
  414.  
  415.         /* move the window horizontally */
  416.         if (deltax != 0 && (diagflag || deltay == 0)) {
  417.             lastwp->w_fcol += deltax;
  418.             if (lastwp->w_fcol < 0)
  419.                 lastwp->w_fcol = 0;
  420.             lastwp->w_flag |= WFMODE|WFHARD;
  421.             if (deltay == 0)
  422.                 return(TRUE);
  423.         }
  424.  
  425.         /* don't allow the bottom modeline to move */
  426.         if (lastwp->w_wndp == NULL)
  427.             return(FALSE);
  428.  
  429.         /* shrink the current window */
  430.         if (deltay > 0) {
  431.             if (lastwp != wp)
  432.                 return(FALSE);
  433.             curwp = wp;
  434.             curbp = wp->w_bufp;
  435.             return(shrinkwind(TRUE, deltay));
  436.         }
  437.  
  438.         /* or grow it */
  439.         if (deltay < 0) {
  440.             if (wp != lastwp->w_wndp)
  441.                 return(FALSE);
  442.             curwp = lastwp;
  443.             curbp = lastwp->w_bufp;
  444.             return(enlargewind(TRUE, -deltay));
  445.         }
  446.     }
  447.  
  448.     /* did we up click in a modeline? fail it them */
  449.     if (ismodeline(wp, ypos) != FALSE)
  450.         return(FALSE);
  451.  
  452.     /* we can not move outside the current window */
  453.     if (lastwp != wp)
  454.         return(FALSE);
  455.  
  456.     /* move horizontally as well? */
  457.     if (deltax != 0 && (diagflag || deltay == 0)) {
  458.         wp->w_fcol += deltax;
  459.         if (wp->w_fcol < 0)
  460.             wp->w_fcol = 0;
  461.         wp->w_flag |= WFMODE;
  462.     }
  463.  
  464.     /* and move the screen */
  465.     return(mvdnwind(TRUE, deltay));
  466. }
  467.  
  468. /*
  469.  * Return a pointer to the WINDOW structure
  470.  * for the window in which "row" is located, or NULL
  471.  * if "row" isn't in any window. The mode line is
  472.  * considered to be part of the window.
  473.  */
  474.  
  475. WINDOW *PASCAL NEAR mousewindow(row)
  476.  
  477. register int    row;
  478.  
  479. {
  480.     register WINDOW    *wp;
  481.  
  482.     /* must be a positiove row! */
  483.     if (row < 0)
  484.         return(NULL);
  485.  
  486.     /* step through each window on the active screen */
  487.     wp = wheadp;
  488.     while (wp != NULL) {
  489.  
  490.         /* is this row within the current window? */
  491.         if (row < wp->w_ntrows+1)
  492.             return(wp);
  493.  
  494.         /* advance to the next window */
  495.         row -= wp->w_ntrows+1;
  496.         wp = wp->w_wndp;
  497.     }
  498.     return(NULL);
  499. }
  500.  
  501. /*
  502.  * The row "row" is a row within the window
  503.  * whose WINDOW structure is pointed to by the "wp"
  504.  * argument. Find the associated line, and return a pointer
  505.  * to it. Return NULL if the mouse is on the mode line,
  506.  * or if the mouse is pointed off the end of the
  507.  * text in the buffer.
  508.  */
  509.  
  510. LINE *PASCAL NEAR mouseline(wp, row)
  511.  
  512. register WINDOW    *wp;
  513. register int    row;
  514.  
  515. {
  516.     register LINE    *lp;
  517.  
  518.     row -= wp->w_toprow;
  519.     if (row >= wp->w_ntrows + (modeflag ? 0 : 1))
  520.         return(NULL);
  521.     lp = wp->w_linep;
  522.     while (row--) {
  523.         if (lp == wp->w_bufp->b_linep)    /* Hit the end.        */
  524.             return(NULL);
  525.         lp = lforw(lp);
  526.     }
  527.     return(lp);
  528. }
  529.  
  530. /*
  531.  * Return the best character offset to use
  532.  * to describe column "col", as viewed from the line whose
  533.  * LINE structure is pointed to by "lp".
  534.  */
  535.  
  536. PASCAL NEAR mouseoffset(wp, lp, col)
  537.  
  538. register WINDOW *wp;
  539. register LINE    *lp;
  540. register int    col;
  541.  
  542. {
  543.     register int    c;
  544.     register int    offset;
  545.     register int    curcol;
  546.     register int    newcol;
  547.  
  548.     offset = 0;
  549.     curcol = 0;
  550.     col += wp->w_fcol;    /* adjust for extended lines */
  551.     while (offset != llength(lp)) {
  552.         newcol = curcol;
  553.         if ((c=lgetc(lp, offset)) == '\t')
  554.             newcol += -(newcol % tabsize) + (tabsize - 1);
  555.         else if (c<32)    /* ISCTRL */
  556.             ++newcol;
  557.         ++newcol;
  558.         if (newcol > col)
  559.             break;
  560.         curcol = newcol;
  561.         ++offset;
  562.     }
  563.     return(offset);
  564. }
  565.  
  566. PASCAL NEAR mouse_screen()
  567.  
  568. {
  569.     register SCREEN *screen_ptr;    /* screen to test mouse in */
  570.  
  571.     /* if we move the mouse off the windows, check for other windows */
  572.     if ((ypos < term.t_roworg) || (xpos < term.t_colorg) ||
  573.         (ypos > term.t_roworg + term.t_nrow) ||
  574.         (xpos >= term.t_colorg + term.t_ncol)) {
  575.  
  576.         /* scan through the other windows */
  577.         screen_ptr = first_screen->s_next_screen;
  578.         while (screen_ptr != (SCREEN *)NULL) {
  579.  
  580.             /* is the mouse in this window? */
  581.             if ((ypos >= screen_ptr->s_roworg) &&
  582.                 (xpos >= screen_ptr->s_colorg) &&
  583.                 (ypos <= screen_ptr->s_roworg + screen_ptr->s_nrow) &&
  584.                 (xpos <= screen_ptr->s_colorg + screen_ptr->s_ncol)) {
  585.  
  586.                     /* select this screen */
  587.                 select_screen(screen_ptr, FALSE);
  588.                 lastxpos = -1;
  589.                 lastypos = -1;
  590.                 break;
  591.             }
  592.  
  593.             /* on to the next screen */
  594.             screen_ptr = screen_ptr->s_next_screen;
  595.         }
  596.     }
  597. }
  598.  
  599. PASCAL NEAR ismodeline(wp, row)
  600.  
  601. WINDOW    *wp;
  602. int row;
  603.  
  604. {
  605.     if (row == wp->w_toprow+wp->w_ntrows && modeflag)
  606.         return(TRUE);
  607.     return(FALSE);
  608. }
  609.  
  610. /* The mouse has been used to resize the physical window. Now we need to
  611.    let emacs know about the newsize, and have him force a re-draw
  612. */
  613.  
  614. PASCAL NEAR resizm(f, n)
  615.  
  616. int f, n;    /* these are ignored... we get the new size info from
  617.            the mouse driver */
  618. {
  619. #if    WINDOW_TEXT
  620.     register int redraw_needed;    /* is a screen redraw required */
  621. #endif
  622.  
  623.     /* make sure we are on the proper screen */
  624.     mouse_screen();
  625.  
  626.     /* adjust position by screen offset */
  627.     ypos -= term.t_roworg;
  628.     xpos -= term.t_colorg;
  629.  
  630. #if    WINDOW_TEXT
  631.         if (xpos < term.t_ncol || ypos < term.t_nrow)
  632.             redraw_needed = TRUE;
  633.         else
  634.             redraw_needed = FALSE;
  635. #endif
  636.  
  637.     /* change to the new size */
  638.     newwidth(TRUE, xpos + 1);
  639.     newsize(TRUE, ypos + 1);
  640.  
  641. #if    WINDOW_TEXT
  642.     if (redraw_needed) {
  643.         refresh_screen(first_screen);
  644.     }
  645. #endif
  646.     return(TRUE);
  647. }
  648.  
  649. #else
  650. mousehello()
  651. {
  652. }
  653. #endif
  654.